<meta http-equiv="content-type" content="text/html; charset=UTF-8">

<link href="https://cas.nuoya.io/md/css/markdown.css" rel="stylesheet" />

<link href="https://cas.nuoya.io/md/css/prettify.css" rel="stylesheet" />

<script src="https://cdn.bootcss.com/zepto/1.2.0/zepto.min.js"></script>

<script src="https://cas.nuoya.io/md/js/prettify.js?t=2"></script>

<h1 id="-">零基础前端编程快速入门</h1>
<p>（作者：喻华锋 2017年6月17日，该内容属于【零基础成为编程高手】书籍内容）</p>
<blockquote>
<p>缘溪行，忘路之远近。忽逢桃花林，夹岸数百步，中无杂树，芳草鲜美，落英缤纷。渔人甚异之。复前行，欲穷其林。林尽水源，便得一山，山有小口，仿佛若有光。便舍船，从口入。初极狭，才通人。复行数十步，豁然开朗。土地平旷，屋舍俨然，有良田美池桑竹之属。阡陌交通，鸡犬相闻。——【陶渊明·桃花源记】</p>
</blockquote>
<p>人们常说隔行与隔山，一个不懂编程的人，永远听不懂我们在说什么，懂得一些理论知识的人，能看懂一些代码，但是如何动手写代码，确无从下手。因为，你并没有系统地了解整个前端编程原理、架构。不明白一个新的项目该如下开始，不明白为什么要这样操作，出了问题，该如何解决。</p>
<p>不是说初学者有多笨，主要原因在于没有一个系统的指引，引导初学者找到前端编程的大门，初学者兜来兜去，不知道入口在哪里，花了再多的气力，都无功而返。</p>
<p>其实你要找的屋子就在那里，你与屋子不过就隔了一层窗户纸而已，戳开了，就什么都明白了。</p>
<p>也许你问了这个、那个，得到的永远是一个个结果片段，可是没有人愿意花十个小时，为你详细讲解这些结果到底是怎么来的，它的第一个字符是如何开始的，他们或许自己都稀里糊涂，或许知道一些却不系统，或许大概懂得可是不知如何表达，要怎么跟你讲呢？何况这也不是一句两句说得清楚的呀！</p>
<p>本文试图从一行代码开始，一步步引导零基础者，快速掌握前端系列编程技术，戳破那层窗户纸，翻窗而入，进入高级编程殿堂。</p>
<h2 id="node-js-">node.js安装</h2>
<p>打开命令提示符窗口，运行 node -v，如果出来版本号，说明安装好了，如果没有，则需要安装 node.js</p>
<p>网站<code>https://nodejs.org/en/</code>下载 最新版本，注意操作系统版本对应，32位、64位、苹果、linux等。
按缺省安装，一次不行，重启电脑，再安装，不要修改安装路径，安装文件不大！</p>
<p>一般安装在 C:\Program Files\nodejs 路径！
安装完毕，重新 打开 命令提示符窗口，再次运行 node -v
如果 出来版本号，恭喜你，node.js 安装成功！</p>
<p>执行命令：npm -v</p>
<p><strong>如果 出来版本号，恭喜你，npm 安装成功，你已经成功迈出了第一步！</strong></p>
<h2 id="node-js-npm-node-package-manager-">node.js 库管理 npm（node package manager）</h2>
<h3 id="npm-">npm 库服务器指向淘宝镜像</h3>
<p>默认库服务器指向国外的，安装非常慢，必须将指向设置为淘宝镜像。</p>
<p>命令行运行 npm config list 指令，看是不是包含以下内容：
disturl = &quot;<a href="https://npm.taobao.org/dist">https://npm.taobao.org/dist</a>&quot;
registry = &quot;<a href="https://registry.npm.taobao.org/">https://registry.npm.taobao.org/</a>&quot;</p>
<p>如果没有，则需重新设置，命令行下分别执行如下两个指令：</p>
<pre><code class="lang-js">npm config set registry https://registry.npm.taobao.org
npm config set disturl https://npm.taobao.org/dist
</code></pre>
<p>执行完毕，再通过 npm config list目录查看是否设置成功！</p>
<p><strong>如果 看到设置的内容，恭喜你，几百万库等你随意快速安装啦！</strong></p>
<h3 id="node-">node全局库清除</h3>
<p>全局安装的库，在任何项目都可使用，项目安装的包，只在当前项目有效。</p>
<p>推荐使用项目安装，除非个别需要全局经常使用的工具除外。
因为项目安装能通过 npm i 一键安装依赖库，而全局安装需手动操作，麻烦。</p>
<p>先看下安装了什么全局库，把安装的全部卸载，重新安装全局库！</p>
<p>npm list -g -depth 0 看下全局安装了 什么库！</p>
<p>比如我的：</p>
<pre><code class="lang-js">cnpm@4.5.0
gulp-cli@1.2.2
typescript@2.3.4
webpack@2.2.1
</code></pre>
<p>全局库安装在 C:\Users\你的用户名\AppData\Roaming\npm
这个目录不能被修改，尽量少安装全局库，除非少数几个全局需要使用的工具库，其他的全部安装到项目目录中！
直接把 C:\Users\你的用户名\AppData\Roaming\npm 这个目录删除！</p>
<p>在执行命令：npm list -g -depth 0，看是不是空的？</p>
<p><strong>如果是空的，恭喜你，全局库不会干扰你啦！</strong></p>
<p>单独卸载全局库： </p>
<p>npm un -g 包名称，如：
npm un typescript -g</p>
<h3 id="-">安装全局库</h3>
<p>gulp、webpack、typescript、babel 四个常用工具库：</p>
<ul>
<li>gulp 用于批量自动化执行，用这个完成编译</li>
<li>webpack 用于js文件打包，用这个完成js文件打包，所谓打包就是把各种引用的js打包到一个js文件！</li>
<li>typescript 是支持es6、7以及静态类型的高级js编译为 js 低版本，兼容旧版本浏览器，这个将来要用！</li>
<li>babel 是支持es6、7 新版本js编译为 js 低版本，兼容旧版本浏览器！</li>
</ul>
<p>批量安装：
npm i -g gulp-cli webpack typescript babel-cli</p>
<p>也可以单独安装： 
npm i -g 包名称，如：
npm i -g typescript</p>
<p>执行命令：npm list -g -depth 0
输出：</p>
<pre><code class="lang-js">C:\Users\xxx\AppData\Roaming\npm
+-- babel-cli@6.24.1
+-- gulp-cli@1.3.0
+-- typescript@2.3.4
`-- webpack@2.6.1
</code></pre>
<p>如果出来以上四个库（版本不一定相同）的话</p>
<p><strong>恭喜你，全局工具库安装成功！</strong></p>
<h3 id="-html5-">创建最简单的 Html5程序</h3>
<p>我们现在要创建一个最简单的项目，就是在屏幕上弹出一个 hello！</p>
<p>在 D盘 创建一个 prj 目录，如果之前有prj，觉得碍眼，可以把之前的修改为 prjx，
在 prj 里面再创建 一个 hello 目录，
hello 目录创建一个 hello.html 的文本文件，内容如下： </p>
<pre><code class="lang-js">&lt;!DOCTYPE html&gt;
&lt;head&gt;
  &lt;title&gt;hello&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
  hello!
&lt;script type=&quot;text/javascript&quot;&gt;
  alert(&#39;hello!&#39;);
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p>用浏览器打开这个文件，如果看到 页面标题、内容和弹出的都是 hello！</p>
<p><strong>恭喜你，你已经完成了一个最简单的html5 程序，说明前端编程已入门！</strong></p>
<p>你也许会疑惑，这就是程序吗？不可能这么简单吧！
是的，编程就是一层窗户纸，捅破了，确实非常简单，世界上99.9%的前端程序员，都是戳破这层窗户纸，
登堂入室，成为前端程序员的！</p>
<p>你要继续跟着我，来把这个窗户纸，戳个大窟窿！</p>
<h3 id="-js-">把 js 文件独立出来</h3>
<p>修改 hello.html，内容如下：</p>
<pre><code class="lang-js">&lt;!DOCTYPE html&gt;
&lt;head&gt;
  &lt;title&gt;hello&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
  hello!
&lt;script src=&quot;hello.js?t=1&quot;&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p>在 hello 目录创建一个hello.js 的文本文件，内容如下： </p>
<pre><code class="lang-js">alert(&#39;hello!&#39;);
</code></pre>
<p>用浏览器打开hello.html文件，如果看到 页面标题、内容和弹出的都是 hello！</p>
<p><strong>恭喜你，你已经学会将 js 独立出来了，你的手已经伸进窗户纸里面了！</strong></p>
<p>也许你迫不及待希望把脚也伸进窗户，没关系，我们继续戳这层窗户纸！</p>
<h3 id="-">创建模块化项目</h3>
<p>世界上99%的前端程序员，实际上只是做到上面那步。
根据项目需求，网上找js代码和页面，把js 代码 写在 js文件里面，对页面上的标签（专业名词叫dom）继续操作，
从而实现页面与代码的交互。</p>
<p>所谓交互，无非就是读取用户输入、从服务器获取数据显示给用户之类的。
要实现这些功能，只需要学习相关的库操作即可，因为这款功能，都能找到现成的库来完成，我们要做的，
就是找到这个库，学会使用这个库，就像开车一样，找到车，打开车门，插入钥匙，开起来，打打方向盘，
这些操作，写库的人规定好了，人家怎么规定，我们怎么操作即可，没有为什么！</p>
<p>所以，如果你想成为99%的前端工程师，剩下的工作就是看各种库的说明书，需要的时候，根据说明书操作即可。</p>
<p>但是，世界上还有1%的前端工程师，他们不会这样工作，因为他们觉得这样代码拷贝来拷贝去，人多了，代码越来越乱。
不说多人，就是自己，项目做多了，代码拷贝来拷贝去，也容易乱呀！
不说代码拷贝来拷贝去，把越来越多的js代码堆积到一个文件里面，维护、修改都是一个非常困难的工作呀！</p>
<p>这1%的工程师，需要清晰的层次、功能的封装、简单的重用、冲突的避免，这就需要引入代码的模块封装、
模块引用、模块合并打包等功能。</p>
<p>因此，我们需要使用 gulp 及 webpack及一系列工具库。
使用这两个工具非常简单，我们需要重新组织文件路径！</p>
<p>hello 目录中创建 src 目录 和 dist 目录，将 hello.html 和 hello.js 拷贝到 src 目录，注意没有js目录，js与html文件同级！</p>
<p>命令行切换到hello 目录，执行命令： dir src</p>
<pre><code class="lang-js">    目录: D:\prj\hello\src
Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       2017-06-17     18:55            123 hello.html
-a----       2017-06-17     18:55             16 hello.js
</code></pre>
<p>如果 src 中已经有了以上两个文件。</p>
<p><strong>恭喜你，项目目录组织成功，你开始向高级程序员前进</strong></p>
<h3 id="-">创建项目依赖库</h3>
<p>在 hello目录 创建 package.json 文本文件，文件内容如下：</p>
<pre><code class="lang-js">{
  &quot;name&quot;: &quot;hello&quot;,
  &quot;version&quot;: &quot;1.0.0&quot;,
  &quot;description&quot;: &quot;hello&quot;,
  &quot;author&quot;: &quot;hello&quot;,
  &quot;scripts&quot;: {
    &quot;start&quot;: &quot;gulp&quot;,
    &quot;build&quot;: &quot;&quot;
  },
  &quot;repository&quot;: {
    &quot;type&quot;: &quot;git&quot;,
    &quot;url&quot;: &quot;&quot;
  },
  &quot;license&quot;: &quot;MIT&quot;,
  &quot;devDependencies&quot;: {
    &quot;awesome-typescript-loader&quot;: &quot;^3.1.3&quot;,
    &quot;browser-sync&quot;: &quot;^2.18.12&quot;,
    &quot;gulp&quot;: &quot;^3.9.1&quot;,
    &quot;gulp-autoprefixer&quot;: &quot;^3.1.0&quot;,
    &quot;gulp-clean&quot;: &quot;^0.3.1&quot;,
    &quot;gulp-concat&quot;: &quot;^2.6.0&quot;,
    &quot;gulp-connect&quot;: &quot;^2.3.1&quot;,
    &quot;gulp-cssnano&quot;: &quot;^2.0.0&quot;,
    &quot;gulp-ext-replace&quot;: &quot;^0.3.0&quot;,
    &quot;gulp-header&quot;: &quot;^1.7.1&quot;,
    &quot;gulp-htmlmin&quot;: &quot;^3.0.0&quot;,
    &quot;gulp-if&quot;: &quot;^2.0.1&quot;,
    &quot;gulp-less&quot;: &quot;^3.0.5&quot;,
    &quot;gulp-markdown&quot;: &quot;^1.2.0&quot;,
    &quot;gulp-postcss&quot;: &quot;^6.0.1&quot;,
    &quot;gulp-rename&quot;: &quot;^1.2.2&quot;,
    &quot;gulp-replace&quot;: &quot;^0.5.2&quot;,
    &quot;gulp-tap&quot;: &quot;^0.1.3&quot;,
    &quot;gulp-typescript&quot;: &quot;^3.1.7&quot;,
    &quot;gulp-uglify&quot;: &quot;^1.5.3&quot;,
    &quot;lodash&quot;: &quot;^4.17.4&quot;,
    &quot;raw-loader&quot;: &quot;^0.5.1&quot;,
    &quot;source-map-loader&quot;: &quot;^0.2.1&quot;,
    &quot;typescript&quot;: &quot;^2.3.4&quot;,
    &quot;vinyl-named&quot;: &quot;^1.1.0&quot;,
    &quot;webpack&quot;: &quot;^2.6.1&quot;
  },
  &quot;dependencies&quot;: {}
}
</code></pre>
<p>里面大部分都是 gulp自动化工具用到的各种插件。<br>插件说明网址：<a href="http://gulpjs.com/plugins/">http://gulpjs.com/plugins/</a></p>
<p>命令行 路径切换到 hello 路径， dir 看下，确认在 hello 路径！
执行指令： npm i</p>
<p>如果提示错误，看下是否有个 package.lock文件，把这个文件删除再试。</p>
<p>该指令 安装 package.json 中指定的 各种库，这些库在打包、压缩js，拷贝文件，自动处理文件等功能时，需要使用。
不要问我怎么知道用这些库，都是网上查的，需要哪个功能，就找，找到了，加到 这个 package.json中。</p>
<p>附加技巧：</p>
<p>安装项目依赖库时，自动将该库加入到 package.json文件，方便迁移的指令如下。</p>
<p>安装开发依赖库，就是开发是需要，运行时不需要：
npm i -D 库1 库2  </p>
<p>安装运行依赖库，就是部署运行时需要：
npm i -S 库2 库2</p>
<p>如果不带 -D 或 -S，就不会自动加入到 package.json，项目迁移时，就不能 npm i，一次性安装所有依赖库！</p>
<p>执行 npm list -depth 0，如果 package.json中的依赖库都安装成功了，</p>
<p><strong>恭喜你，你已经学会创建、安装项目依赖库，一只脚已经穿过了窗户啦！</strong></p>
<p>我们继续戳破这层窗户纸，把另外一只脚伸进去！</p>
<h3 id="-es6-7-ts-">安装 es6、7及ts 编译器</h3>
<p>编译器有两种，一种是 babel，一种是 typescript，babel 太过灵活，配置复杂，安装的库也很多，
我们简单一点，直接使用 ts吧！</p>
<p>本地项目安装指令，注意，需在 hello 目录执行：</p>
<p><code>npm i -D typescript gulp-typescript awesome-typescript-loader source-map-loader</code></p>
<p>安装了四个库，实际上以上库会保存到 package.json，下次通过 npm i 可以自动安装的，这里为了理解，单独安装。</p>
<p>在 hello 目录 增加 tsconfig.json 文件，控制tsc编译转换行为，参考内容如下；</p>
<pre><code class="lang-js">{
  &quot;compilerOptions&quot;: {
    &quot;outDir&quot;: &quot;./built&quot;,
    &quot;allowJs&quot;: true,
    &quot;lib&quot;: [&quot;dom&quot;, &quot;es2015.promise&quot;, &quot;es5&quot;],
    &quot;module&quot;: &quot;commonjs&quot;,
    &quot;target&quot;: &quot;es5&quot;,
    &quot;noImplicitAny&quot;: false,
    &quot;sourceMap&quot;: true
  },
  &quot;exclude&quot;: [
    &quot;node_modules&quot;
  ],
  &quot;files&quot;: [
    &quot;src/hello.ts&quot;
  ]
}
</code></pre>
<ul>
<li>tsconfig.json 文件参数说明<ul>
<li>target：编译之后生成的JavaScript文件需要遵循的标准。有三个候选项：es3、es5、es2015。</li>
<li>noImplicitAny：为false时，如果编译器无法根据变量的使用来判断类型时，将用any类型代替。为true时，将进行强类型检查，无法推断类型时，提示错误。</li>
<li>module：遵循的JavaScript模块规范。主要的候选项有：commonjs、AMD和es6。</li>
<li>removeComments：编译生成的JavaScript文件是否移除注释。</li>
<li>sourceMap：编译时是否生成对应的source map文件。这个文件主要用于前端调试。当前端js文件被压缩引用后，出错时可借助同名的source map文件查找源文件中错误位置。</li>
<li>outDir：编译输出JavaScript文件存放的文件夹。</li>
<li>include、exclude：编译时需要包含/剔除的文件夹。</li>
</ul>
</li>
</ul>
<h3 id="-webpack-">使用 webpack 实现前端模块化编程</h3>
<p>所谓模块化，就是支持代码通过模块化封装与引用，把一些逻辑封装到模块中，模块之间能方便互相引用。</p>
<p>js 最大的缺陷之一，就是不支持模块，而其它所有语言，基本都支持模块化。
而前端，一直以来，不支持模块化功能，导致前端程序员不懂什么叫模块化。
虽然es6增加了模块化功能，可是绝大部分浏览器目前还不支持es6！</p>
<p>后端 node.js 对js 进行了扩展，增加了模块化功能，才导致 js 能编写服务端程序。</p>
<p>幸好有个webpack 工具引入了前端js的模块化管理，我们如果要用js开发大型系统，模块化是必须的功能。</p>
<p>webpack 我们在 npm 中已经安装了，只需要 在 hello目录中增加一个 webpack.config.js 即可！
该配置文件在 运行 webpack时起作用，用于控制webpakc打包行为。</p>
<p>webpack 是针对es5低版本js进行模块化管理与打包的。
如果源文件使用了es6、es7、ts功能，则需要先将高级版本编译转换为低版本时，才能工作。</p>
<p>，babel loader，同时对js、ts文件进行编译打包，前端工程需要，后端不需要打包为一个文件！</p>
<p>参考 webpack.config.js 内容如下（注意，是<code>js和</code>中间的内容）：</p>
<pre><code class="lang-js">/**
 * Created by way on 16/6/11.
 */
var path = require(&#39;path&#39;);
var webpack = require(&#39;webpack&#39;);

// 插件配置
var getPlugins = function(env) {
    var defaultPlugins = [
        // 这个不仅是别名，还可以在遇到别名的时候自动引入模块
        new webpack.ProvidePlugin({
            &#39;$&#39;: &#39;jquery.js&#39;,
            &#39;jquery&#39;: &#39;jquery.js&#39;,
            &#39;jQuery&#39;: &#39;jquery.js&#39;,
        }),
        // 抽离公共模块
        new webpack.optimize.CommonsChunkPlugin(&#39;common&#39;, &#39;common.js&#39;),
        new ExtractTextPlugin(
            path.join(&#39;../../stylesheets&#39;, project, &#39;/[name].css&#39;), {
                allChunks: true
            }
        )
    ];

    if (env == &#39;production&#39;) {
        // 线上模式的配置，去除依赖中重复的插件/压缩js/排除报错的插件
        plugins = _.union(defaultPlugins, [
            new webpack.optimize.DedupePlugin(),
            new webpack.optimize.UglifyJsPlugin({
                sourceMap: false,
                mangle: {
                    except: [&#39;$&#39;, &#39;jQuery&#39;]
                }
            }),
            new webpack.NoErrorsPlugin()
        ]);
    } else {
        plugins = _.union(defaultPlugins, []);
    }

    return plugins;
};

module.exports = {
  entry: {hello: &#39;./src/hello.js&#39;}, // gulp 输入
  output: {
    path: path.resolve(__dirname, &#39;dist/js&#39;), // string
    filename: &#39;[name].js&#39;
  },
  resolve: {
    // options for resolving module requests
    // (does not apply to resolving to loaders)
    modules: [
      &#39;node_modules&#39;,
      path.resolve(__dirname, &#39;src&#39;)
    ],
    // directories where to look for modules
    extensions: [&#39;.js&#39;, &#39;.ts&#39;]
    // extensions that are used
  },
  watch: false,
  profile: true,
  cache: true,
  module: {
    rules: [
      { test: /\.(ts|js)$/, loader: &#39;awesome-typescript-loader&#39;, 
        include: [path.resolve(__dirname, &#39;src&#39;)],
        exclude: [path.resolve(__dirname, &#39;node_modules&#39;)]
      }
    ]
  },
  externals: {
    // Zepto: &#39;Zepto&#39;,
    EditTable: &#39;EditTable&#39;
  }
};
</code></pre>
<h3 id="-">测试前端模块化功能</h3>
<p>在 hello目录中，运行指令：
<code>webpack</code></p>
<p>如果 在 dist/js 目录中，生成了 hello.js 文件，文件内如如下：</p>
<pre><code class="lang-js">/******/ (function(modules) { // webpackBootstrap
/******/     // The module cache
/******/     var installedModules = {};
/******/
/******/     // The require function
/******/     function __webpack_require__(moduleId) {
/******/
/******/         // Check if module is in cache
/******/         if(installedModules[moduleId]) {
/******/             return installedModules[moduleId].exports;
/******/         }
/******/         // Create a new module (and put it into the cache)
/******/         var module = installedModules[moduleId] = {
/******/             i: moduleId,
/******/             l: false,
/******/             exports: {}
/******/         };
/******/
/******/         // Execute the module function
/******/         modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/         // Flag the module as loaded
/******/         module.l = true;
/******/
/******/         // Return the exports of the module
/******/         return module.exports;
/******/     }
/******/
/******/
/******/     // expose the modules object (__webpack_modules__)
/******/     __webpack_require__.m = modules;
/******/
/******/     // expose the module cache
/******/     __webpack_require__.c = installedModules;
/******/
/******/     // identity function for calling harmony imports with the correct context
/******/     __webpack_require__.i = function(value) { return value; };
/******/
/******/     // define getter function for harmony exports
/******/     __webpack_require__.d = function(exports, name, getter) {
/******/         if(!__webpack_require__.o(exports, name)) {
/******/             Object.defineProperty(exports, name, {
/******/                 configurable: false,
/******/                 enumerable: true,
/******/                 get: getter
/******/             });
/******/         }
/******/     };
/******/
/******/     // getDefaultExport function for compatibility with non-harmony modules
/******/     __webpack_require__.n = function(module) {
/******/         var getter = module &amp;&amp; module.__esModule ?
/******/             function getDefault() { return module[&#39;default&#39;]; } :
/******/             function getModuleExports() { return module; };
/******/         __webpack_require__.d(getter, &#39;a&#39;, getter);
/******/         return getter;
/******/     };
/******/
/******/     // Object.prototype.hasOwnProperty.call
/******/     __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/     // __webpack_public_path__
/******/     __webpack_require__.p = &quot;&quot;;
/******/
/******/     // Load entry module and return exports
/******/     return __webpack_require__(__webpack_require__.s = 0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports) {

alert(&#39;hello!&#39;);


/***/ })
/******/ ]);
</code></pre>
<p><strong>恭喜你，非常了不起，要知道，会这个功能的前端程序员，全世界不足1%！</strong></p>
<p>第二只脚也进了房间，确实很牛。</p>
<p>高级知识补充：</p>
<p>打包后的文件就要说明。</p>
<p>hello.js 源文件只有一行代码  alert(&#39;hello!&#39;);，模块化后，头部增加了很多代码，其中</p>
<pre><code class="lang-js">/******/ ([
/* 0 */
/***/ (function(module, exports) {

alert(&#39;hello!&#39;);


/***/ })
/******/ ]);
</code></pre>
<p>我们把注释去掉，会发现  alert(&#39;hello!&#39;); 被封装到数组里面的函数中了，编号为0，
如果我们有多个文件，这个数组就有多个函数封装，每个js文件一个函数封装。</p>
<p>为什么要封装到函数中？</p>
<p>因为 js 的变量是按 函数隔离的，项目中如果有很多js文件定义了变量 x 的话，把文件封装到函数中，
每个文件中的 x 都是不同的，只在当前文件生效，不影响其他文件，否则会出现 x 冲突！</p>
<pre><code class="lang-js">([
  (function(module, exports) {
    alert(&#39;hello!&#39;);
  })
]);
</code></pre>
<p>这个文件是页面最终引用的文件，它就是标准的es5版本js，跟我们自己编写的没什么不同，
理解这个原理，就不会觉得编译、打包神秘，出了问题，也不知道如何解决！</p>
<p>很简单，直接打开生成后的js文件，关闭自动 gulp生成，直接修改这个 打包后的js文件，
比如 加入 alert提示，或者 debugger 调试功能。</p>
<h3 id="-">自动化构建</h3>
<p>除了处理js文件之外，程序发布还需要处理 less、html等文件，比如空白处理，文件拷贝等，
每次手动操作，工作量非常大，有个强大的工具，能帮我们自动检测源代码的修改，检测到修改后，
能自动执行一段脚本，完成特定任务。</p>
<p>这个工具就是大名鼎鼎的 gulp，脚本 就是 gulpfile.js 文件。
把这个文件放到 hello 的根目录。</p>
<p>gulpfile.js 文件内容参考：</p>
<pre><code class="lang-js">/**
 * Created by way on 2015/1/14.
 */
var gulp = require(&#39;gulp&#39;);
var _ = require(&#39;lodash&#39;);

//用于gulp传递参数
var minimist = require(&#39;minimist&#39;);
var path = require(&#39;path&#39;);
var webpack = require(&#39;webpack&#39;);
// var webpack = require(&#39;webpack-stream&#39;); 在 windows 中报错，改用原生方案！
// var logger = require(&#39;gulp-logger&#39;);
var gutil = require(&#39;gulp-util&#39;);
var uglify = require(&#39;gulp-uglify&#39;);
var rename = require(&#39;gulp-rename&#39;);
var less = require(&#39;gulp-less&#39;);
var tap = require(&#39;gulp-tap&#39;);
var pkg = require(&#39;./package.json&#39;);
var named = require(&#39;vinyl-named&#39;);
var gulpif = require(&#39;gulp-if&#39;);
var htmlmin = require(&#39;gulp-htmlmin&#39;);

var dest = &#39;dist/&#39;; 

var opts = {
  string: &#39;env&#39;,
  default: { env: process.env.NODE_ENV || &#39;production&#39; }
};

var options = minimist(process.argv.slice(2), opts);
var wpDevCfg = require(&#39;./webpack.config.js&#39;);
var wpProdCfg = require(&#39;./webpack.config.js&#39;);

// js 打包日志
function packLog(err, msg) {
  if (err)
    throw new gutil.PluginError(&quot;buildjs&quot;, err);
  gutil.log(&quot;[buildjs]&quot;, msg.toString({ colors: true }));
}

// 去掉页面空格，拷贝页面到指定目录
gulp.task(&#39;hello:html&#39;, function () {
  gulp.src(&#39;src/*.html&#39;)
    .pipe(htmlmin({collapseWhitespace: true}))
    .pipe(gulp.dest(dest));
});

// js 异步打包
gulp.task(&#39;hello:pack&#39;, function() {
  var wpcfg = options.env === &#39;production&#39; ? wpProdCfg : wpDevCfg;
  webpack(_.merge(wpcfg, { // 替换 webpack.config.js 里的设置
    entry: {hello: &#39;./src/hello.js&#39;},
    output: {path: path.resolve(__dirname, &#39;dist&#39;)},
    watch: true // 监控js 文件变化，变化后自动再次触发 该任务，以增量方式生成，速度更快
  })).watch(200, function(err, stats) {
    packLog(err, stats);
    // callback(); //异步任务的关键之处，如果没有这行，任务会一直阻塞
  });
});

// 监视html文件任务，文件被修改，自动触发该任务
// js 文件由 webpack自己的 监控完成
gulp.task(&#39;watch&#39;, [&#39;hello:html&#39;], function() {
    gulp.watch(&#39;src/**/*.html&#39;, [&#39;hello:html&#39;]);
});

// 缺省任务，gulp 任务名称，不带任务名称时，执行该任务
gulp.task(&#39;default&#39;, [&#39;watch&#39;, &#39;hello:pack&#39;]);
</code></pre>
<p>在hello 根目录命令行，执行指令：gulp，如果能自动完成 html文件拷贝和js编译打包，</p>
<p><strong>恭喜你，你已经踏进了这个房间，成为那1%的前端工程师！</strong></p>
<h2 id="-">编写高大上的说明文档</h2>
<p>99.9%的程序员都有一个共同的习惯，就是愿意写代码，不愿意写文档，无论是word、ppt、excel，统统都比爱。
可是项目是要合作的，没有文档，合作者该如何使用你写的程序呢？</p>
<p>我们宁愿一遍遍口述，确不愿意顺手写下来。
我是极少数愿意写说明的程序员，但是如果要整理成非常正式的word、excel，也非常不情愿，所以我的开发日志非常非常多，可是正式的word文档却没几个。</p>
<p>github上，每个代码库的第一个页面就是一个说明文档，格式基本一模一样，让我们看起来很舒服，一看就知道怎么安装、使用，赏心悦目，这个文档是用什么写的呢？</p>
<p>markdown，你看到的虽然是html页面，实际上程序员写的是markdown，github自动能将markdown文档转换为HTML。</p>
<p>为什么要用markdown，因为这是程序员发明的文档格式，让我们像写代码一样写文档，是不是很爽！</p>
<p>你现在看到，也是用markdown写的，所有的注意力都在文字、代码上，不用考虑格式、排版等，确实很爽。</p>
<p>markdown具体格式，网上很多，十几分钟即可上手，这里就不讲解。我们现在要做的，是如何将md文件自动转换成html文件，方便其他人浏览。</p>
<p>我们在上节中既然已经学会了如何自动构建，对于gulp来说，小菜一碟！</p>
<p>安装插件：</p>
<p><code>npm i -D gulp-markdown</code></p>
<p>修改 gulpfile.js</p>
<p>在文件头部加入插件引用</p>
<pre><code class="lang-js">var markdown = require(&#39;gulp-markdown&#39;);
</code></pre>
<p>增加 hello:md任务，自动将 md目录中的 md文件转换为html文件。注意，修改了缺省任务</p>
<pre><code class="lang-js">gulp.task(&#39;hello:md&#39;, function () {
  return gulp.src(&#39;md/*.md&#39;)
    .pipe(markdown())
    // 统一转换到 doc 目录
    .pipe(gulp.dest(dest+&#39;doc&#39;))
});


// 缺省任务，gulp 任务名称，不带任务名称时，执行该任务
gulp.task(&#39;default&#39;, [&#39;watch&#39;, &#39;hello:pack&#39;, &#39;hello:md&#39;]);
</code></pre>
<p>我们动手写个 readme.md 放到 md 目录。
文件内容如下：</p>
<pre><code class="lang-js">&lt;meta http-equiv=&quot;content-type&quot; content=&quot;text/html; charset=UTF-8&quot;&gt;

&lt;link href=&quot;https://cas.nuoya.io/md/css/markdown.css&quot; rel=&quot;stylesheet&quot; /&gt;

&lt;link href=&quot;https://cas.nuoya.io/md/css/prettify.css&quot; rel=&quot;stylesheet&quot; /&gt;

&lt;script src=&quot;https://cdn.bootcss.com/zepto/1.2.0/zepto.min.js&quot;&gt;&lt;/script&gt;

&lt;script src=&quot;https://cas.nuoya.io/md/js/prettify.js?t=2&quot;&gt;&lt;/script&gt;

零基础前端编程快速入门
====================

&gt;缘溪行，忘路之远近。忽逢桃花林，夹岸数百步，中无杂树，芳草鲜美，落英缤纷。渔人甚异之。复前行，欲穷其林。林尽水源，便得一山，山有小口，仿佛若有光。便舍船，从口入。初极狭，才通人。复行数十步，豁然开朗。土地平旷，屋舍俨然，有良田美池桑竹之属。阡陌交通，鸡犬相闻。——【陶渊明·桃花源记】

### 零基础前端编程快速入门
====================

## node.js安装

- 网站：https://nodejs.org/en/
- 下载对应版本，按提示安装
</code></pre>
<p>运行 gulp，如果你能在dist的doc目录发现readme.html，能正确看到页面内容的话！</p>
<p><strong>恭喜你，你已经超过99%的程序员</strong></p>
<p>学会了写高大上的markdown文档，并自动转换为html文件，把你的接口文档、说明文档以HTML格式发给老板、客户，他们一定会在心里惊叹，高手就是高手，与一般程序员不一样，你的程序员合作伙伴，心里一定在暗暗骂你，操，你这么牛逼，让我怎么混！</p>
<h2 id="gulp-web-">gulp创建本地WEB服务器及页面自动刷新</h2>
<p>完成 html、css、js文件后，需要在浏览器上查看效果，通过文件浏览器直接打开本地文件方式，如：</p>
<p><code>file:///C:/Users/walter/prj/nydl/nywx/src/hello/dist/hello.html</code></p>
<p>也能看到效果，但是这毕竟跟正式运行时的浏览方式不一样，最好是放到web 服务器中浏览。</p>
<p>服务器上当然部署了web 服务器，只需把文件上传到服务器，通过浏览器访问，就能看到效果。<br>但是，在调试中，文件不断修改，每次上传文件、浏览，确实是非常麻烦的事情。</p>
<p>既然我们有 万能的 gulp 自动化仆人，能帮我们完成所有我们能想到的任务，肯定能找到一个插件，实现本地web 访问。</p>
<p>这个插件 就是 gulp-connect。</p>
<p>修改html、css、js文件后，需要在浏览器上查看效果，一般来说就是打开页面，每次修改，手动刷新页面（F5）。
对于一个前端程序员来说，一天往往要刷新几百次，工作量不小。</p>
<p>有没有一个插件，在我们修改了文件时，能自动刷新页面呢？  </p>
<p>这个插件 就是 gulp-connect。</p>
<p>当然其他的还有：</p>
<ul>
<li>browser-sync</li>
<li>gulp-livereload</li>
</ul>
<p>安装插件：</p>
<p><code>npm i -D gulp-connect gulp-watch</code></p>
<p>修改 gulpfile.js</p>
<p>在文件头部加入插件引用</p>
<pre><code class="lang-js">var connect = require(&#39;gulp-connect&#39;);
var watch = require(&#39;gulp-watch&#39;);
</code></pre>
<p>增加本地web 服务和文件变化自动刷新，注意，修改了缺省任务</p>
<pre><code class="lang-js">// 本地web服务，用于本地调试
gulp.task(&#39;distWeb&#39;, function () {
  connect.server({
    name: &#39;distWeb&#39;,
    root: &#39;dist&#39;, // web服务根目录
    port: 3000, // 端口
    livereload: true
  });
});

// 监控文件变化，变化了则自动刷新本地浏览器
gulp.task(&#39;livereload&#39;, function () {
  watch([&#39;dist/*.html&#39;, &#39;dist/*.js&#39;])
    .pipe(connect.reload());
});

// 缺省任务，gulp 任务名称，不带任务名称时，执行该任务
gulp.task(&#39;default&#39;, [&#39;watch&#39;, &#39;hello:pack&#39;, &#39;hello:md&#39;, &#39;distWeb&#39;, &#39;livereload&#39;]);
</code></pre>
<p>在浏览器中打开 <a href="http://localhost:3000/hello.html，如果能打开页面！">http://localhost:3000/hello.html，如果能打开页面！</a></p>
<p><strong>恭喜你，你已经学会自动创建本地web 服务了！</strong></p>
<p>修改 hello/src/ 下面的 hello.html 文件如下：</p>
<p>hello！  改为 hello2,</p>
<p>如果自动切换到浏览器，并且 页面 上 hello 改为 hello2了！</p>
<p><strong>恭喜你，你已经学会了自动刷新html页面啦！</strong></p>
<p>修改 hello/src/ 下面的 hello.js 文件如下：</p>
<p>alert(&#39;hello！&#39;)  改为 alert(&#39;hello2！&#39;)</p>
<p>如果自动切换到浏览器，并且 页面 上 自动弹出 hello2 ！</p>
<p><strong>恭喜你，你已经学会了修改js自动刷新页面啦！</strong></p>
<p>掌握了本地自动构建、自动刷新，在工作中，调试效率至少提高 30%以上！</p>
<p><strong>恭喜你，你已经成为前端高手了！</strong></p>
